package ru.hh.team02.chat.server;

import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.HashSet;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;

import ru.hh.team02.chat.server.SendMessage.Message;

public class ChatServer {
    private static final int PORT = 2004;  
    private static final int MAX_THREADS = 100;
    
    private static final Executor executor = 
            Executors.newFixedThreadPool(MAX_THREADS);
    private static final MessageSender messageSender = 
            new MessageSender();

    private static HashSet<Client> writers = 
            new HashSet<Client>();
    
    ServerSocket listener;
    
    public static void start() {
        ChatServer server = new ChatServer(); 
        server.run();
    }
    
    /*
     * listens to a port and spawns handlers
     */
    private void run() {
        try {
            listener = new ServerSocket(PORT);
            System.out.println("waiting for connection...");
            while (true) {
                try  {
                    final Socket connection = listener.accept();
                    executor.execute(new Client(connection));      
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                listener.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
    
    /*
     * task, which hangs on client socket and listens to it
     */
    public static class Client implements Runnable {
        private StringSocket socket;
        private String name = "default name";
        
        public Client(Socket socket) {
            this.socket = new StringSocket(socket);
        }

        @Override
        public void run() {
            try {      
                socket.openStreams();
                socket.write("connected");
                synchronized(ChatServer.writers) {
                    ChatServer.writers.add(this);
                }
                
                String message = "";
                do {
                    message = socket.read();
                    handleMessage(name + "> " + message);
                } while (!message.equals("bye"));
            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                synchronized(ChatServer.writers) {
                    ChatServer.writers.remove(this);
                }
                socket.close();
            }
        }
        
        /*
         * puts message in the queue.
         * in current version one message per client (not per room)
         */
        private void handleMessage(String message) {
            System.out.println(message);
            
            synchronized(ChatServer.writers) {
                for (Client p : ChatServer.writers) {
                    ChatServer.messageSender.addMessage(
                            new Message(message, p));
                }
            }
        }
        
        public void sendMe(String message) {
            try {
                socket.write(message);
            } catch (IOException e) {
                System.out.println("can't send message");
            }
        }
    }
}
